#include <iostream>
#include <string>
using namespace std;
//左值：放在赋值语句左侧的东西，代表一个地址
//右值：不能作为左值的即为右值

/**
左值右值：
    c++的一条表达式，要么是左值，要么是右值
    左值能够被当作右值使用
    例如 i=i+1
    一个左值可能同时具有左值和右值的属性
引用分类：
    左值引用
        绑定到左值
            int val=10;
            int&ref=val;//绑定到val这个左值
    常量引用，也是左值引用，不希望改变值得对象
            const int&ref2=a;

    右值引用
        绑定到右值

            int&&ref=20;
            ref=29;//可以通过右值引用直接给右值赋值  

*/
//引用必须初始化，不初始化就会报错
//左值引用必须绑定到左值，不能绑定到右值
//但是如果左值引用前边加上const，const引用可以绑定到右值，const引用非常特殊
    const int&val=10;
//上边得语句等价于下边得
    int temp=10;//一个临时变量
    const int&val1=temp;
//注：
    string str("test");
    string&str2{str};//左值可以绑定管左值
    //
   // string&str8{"hello"};//左值引用不能绑定临时变量，临时变量被当作右值，如果加const就可以执行了
//注意++i 与i++

//++左值表达式


//i++先用后加，i++先产生临时变量temp地
int i=1;
int&&re=i++;
//任何函数地参数都是左值
//临时对象都是右值


//右值引入地目的

//右值引用c++11引入，
//右值引用的目的时提高程序的运行效率，将拷贝对象变成移动对象

//移动对象如何发生
    //用一个对象给其他对象初始化
    //移动拷贝构造函数
    //&&
    //移动拷贝赋值运算符
    

//std::move()函数
//作用：将一个左值转换成右值

int a=10;
int &&right=std::move(a);

string str11="hello world";

//注意下边的两个区别，一个是构造新的阿对象，一个是右值引用
//注意是string里的移动构造函数将str11中的内容移动到str22而不是std::move()
string str22=std::move(str11);//切记string这个地方调用的是string的移动构造函数

string &&str22=std::move(str11);  

